package pers.vic.boot.base.handler.json;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import org.apache.commons.lang3.StringUtils;
import pers.vic.boot.base.handler.json.annotation.AppendJsonField;

import java.io.IOException;
import java.util.Objects;

/**
 * 追加JSON字段的序列化方法
 *
 * @See @AppendJsonField  * use for field like: @AppendJsonField(key="idDesc", keyValyeDesc= {"1:ZHANGSAN", "2:LISI"})
 * @author VIC
 *
 */
public class AppendJsonFieldSerialize extends JsonSerializer<Object> implements ContextualSerializer {

    private String key;

    private String[] keyValueDesc;

    /**
     * 是否是String类型的字段，不是在是Integer
     */
    private boolean isString;

    public AppendJsonFieldSerialize(AppendJsonField appendJsonField, boolean isString) {
        super();
        this.key = appendJsonField.key();
        this.keyValueDesc = appendJsonField.keyValueDesc();
        this.isString = isString;
    }


    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty)
            throws JsonMappingException {
        if (beanProperty != null) {
            Class<?> clzType = beanProperty.getType().getRawClass();
            // 非 Integer类或者String类直接跳过
            boolean validType = Objects.equals(clzType, int.class) || Objects.equals(clzType, Integer.class) || Objects.equals(clzType, String.class);
            if (validType) {
                AppendJsonField appendJsonField = beanProperty.getAnnotation(AppendJsonField.class);
                if (appendJsonField == null) {
                    appendJsonField = beanProperty.getContextAnnotation(AppendJsonField.class);
                }
                // /如果能得到注解，
                if (appendJsonField != null) {
                    return new AppendJsonFieldSerialize(appendJsonField, Objects.equals(clzType, String.class));
                }
            }
            return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
        }
        return serializerProvider.findNullValueSerializer(beanProperty);
    }

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        if (isString) {
            gen.writeString(value + "");
        } else {
            gen.writeNumber(Integer.valueOf(value + ""));

        }

        if (StringUtils.isNoneEmpty(key) && keyValueDesc != null) {
            for (String kv : keyValueDesc) {
                if (kv.split(":").length == 2 && String.valueOf(value).equals(kv.split(":")[0])) {
                    gen.writeStringField(key, kv.split(":")[1]);
                    break;
                }
            }
        }
    }

    public static void main(String[] args) throws JsonProcessingException {
        Test t = new Test();
        t.setType(2);
        t.setName("999");
        ObjectMapper mapper = new ObjectMapper();
        String writeValueAsString = mapper.writeValueAsString(t);
        System.out.println(writeValueAsString);

    }

}

class Test {

    @AppendJsonField(key = "typeName", keyValueDesc = {"1:ZHANGSAN", "2:LISI"})
    int type;

    String name;

    /**
     * @return the type
     */
    public int getType() {
        return type;
    }

    /**
     * @param type
     *            the type to set
     */
    public void setType(int type) {
        this.type = type;
    }

    /**
     * @return the name
     */
    public String getName() {
        return name;
    }

    /**
     * @param name
     *            the name to set
     */
    public void setName(String name) {
        this.name = name;
    }

}
